package com.demo.sso.util;

import com.alibaba.fastjson.JSON;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.*;

import java.util.HashMap;
import java.util.Map;

/**
 * 操作redis的工具类
 *
 * @author fengjy
 * @date 2018-10-30 20:16
 */

@Slf4j
@Data
@Configuration
public class RedisUtil {

    //Redis服务器IPs
    private static String ADDR = "192.168.31.160";

    //Redis的端口号
    private static int PORT = 6379;

    //访问密码
    private static String AUTH = "123456";

    //可用连接实例的最大数目，默认值为8；
    //如果赋值为-1，则表示不限制；如果pool已经分配了maxActive个jedis实例，则此时pool的状态为exhausted(耗尽)。
//    private static int MAX_ACTIVE = 50;

    //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例，默认值也是8。
    private static int MAX_IDLE = 200;

    //等待可用连接的最大时间，单位毫秒，默认值为-1，表示永不超时。如果超过等待时间，则直接抛出JedisConnectionException；
    private static int MAX_WAIT = 10000;

    private static int TIMEOUT = 10000;

    //在borrow一个jedis实例时，是否提前进行validate操作；如果为true，则得到的jedis实例均是可用的；
    private static boolean TEST_ON_BORROW = true;

    private static JedisPool jedisPool = null;

    /**
     * 初始化Redis连接池
     */
    static {
        try {
            log.info("fengjy >>> redis 配置信息 ADDR = [{}], PORT = [{}], AUTH = [{}]", ADDR, PORT, AUTH);
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxIdle(MAX_IDLE);
            config.setMaxWaitMillis(MAX_WAIT);
            config.setTestOnBorrow(TEST_ON_BORROW);
//            if(StringUtils.isEmpty(AUTH)) {
//                AUTH=null;
//            }
            jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT);
//            如果redis需要密码传AUTH，不用不传
//            jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT, AUTH);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取Jedis实例
     * @return
     */
    public synchronized static Jedis getJedis() {
        try {
            if (jedisPool != null) {
                Jedis resource = jedisPool.getResource();
                return resource;
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 释放jedis资源
     * @param jedis
     */
    public static void returnResource(final Jedis jedis) {
        if (jedis != null) {
            jedisPool.returnResource(jedis);
        }
    }

    /**
     * KEY对应value加1,并且设置过期时间
     * @param db
     * @param key
     * @param ttl(s)
     * @return
     */
    public static long incrWithExpire(int db, String key, int ttl){
        Jedis resource=null;
        long res = 0;
        try {
            if (jedisPool != null) {
                resource = jedisPool.getResource();
                resource.select(db);
                res = resource.incr(key);
                if(res == 1){
                    resource.expire(key, ttl);
                }

                jedisPool.returnResource(resource);
            }
            return res;
        } catch (Exception e) {
            e.printStackTrace();
            jedisPool.returnBrokenResource(resource);
            return 0;
        }
    }

    /**
     * 删除set中多个fields
     * @param db
     * @param key
     * @return
     */
    public static long hdel(int db, String key, String[] fields){
        Jedis resource=null;
        long res = 0;
        try {
            if (jedisPool != null) {
                resource = jedisPool.getResource();
                resource.select(db);
                res = resource.hdel(key, fields);

                jedisPool.returnResource(resource);
            }
            return res;
        } catch (Exception e) {
            e.printStackTrace();
            jedisPool.returnBrokenResource(resource);
            return 0;
        }
    }
    /**
     * 获取Redis里面的set里的值
     * @param db
     * @param key
     * @param feild
     * @return
     */
    public static String hget(int db,String key,String feild){
        Jedis jedis = null;
        String value = null;
        try {
            if (jedisPool!=null) {
                jedis = jedisPool.getResource();
                jedis.select(db);
                value=jedis.hget(key,feild);
                jedisPool.returnResource(jedis);
            }
        }catch (Exception e){
            e.printStackTrace();;
            jedisPool.returnBrokenResource(jedis);
        }
        return value;
    }
    /**
     * 写入Redis里面的set里的值
     * @param db
     * @param key
     * @param feild
     * @return
     */
    public static void hset(int db,String key,String feild,String value){
        Jedis jedis = null;
        try{
            if(jedisPool!=null){
                jedis = jedisPool.getResource();
                jedis.select(db);
                jedis.hset(key,feild,value);
                jedisPool.returnResource(jedis);
            }
        }catch (Exception e){
            e.printStackTrace();
            jedisPool.returnBrokenResource(jedis);
        }
    }


    /**
     * 迭代set里的元素
     * @param db
     * @param key
     * @return
     */
    public static ScanResult<Map.Entry<String,String>> hscan(int db, String key, String cursor, ScanParams scanParams){
        Jedis resource=null;
        ScanResult<Map.Entry<String,String>> scanResult = null;
        try {
            if (jedisPool != null) {
                resource = jedisPool.getResource();
                resource.select(db);
                scanResult = resource.hscan(key, cursor, scanParams);

                jedisPool.returnResource(resource);
            }
            return scanResult;
        } catch (Exception e) {
            e.printStackTrace();
            jedisPool.returnBrokenResource(resource);
            return scanResult;
        }
    }

    public static void main(String[] args) {
        System.out.println(incrWithExpire(0, "test", 10));
        ScanParams scanParams = new ScanParams();
        scanParams.count(10);
        Map<String, String> map = new HashMap<String, String>();
        System.out.println(JSON.toJSONString(hscan(2, "cuserMobileCabSet", "0", scanParams)));
    }


    /**
     * 获取byte类型数据
     * @param key
     * @return
     */
    public static byte[] getObject(int db,byte[] key,int expireTime){
        Jedis jedis = getJedis();
        byte[] bytes = null;
        if(jedis != null){
            jedis.select(db);
            try{
                bytes = jedis.get(key);
                if(null != bytes){
                    jedis.expire(key,expireTime);
                }
            }catch(Exception e){
                e.printStackTrace();
            } finally{
                returnResource(jedis);
            }
        }
        return bytes;
    }

    /**
     * 保存byte类型数据
     * @param key
     * @param value
     */
    public static void setObject(int db,byte[] key, byte[] value,int expireTime){
        Jedis jedis = getJedis();
        if(jedis != null){
            jedis.select(db);
            try{
                jedis.set(key, value);
                // redis中session过期时间
                jedis.expire(key, expireTime);
            } catch(Exception e){
                e.printStackTrace();
            } finally{
                returnResource(jedis);
            }
        }
    }

    /**
     * 更新byte类型的数据，主要更新过期时间
     * @param key
     */
    public static void updateObject(int db,byte[] key,byte[] value,int expireTime){
        Jedis jedis = getJedis();
        if(jedis != null){
            try{
                // redis中session过期时间
                jedis.select(db);
                jedis.set(key, value);
                jedis.expire(key, expireTime);
            }catch(Exception e){
                e.printStackTrace();
            } finally{
                returnResource(jedis);
            }
        }
    }

    /**
     * 删除字符串数据
     * @param key
     */
    public static void delString(int db ,String key){
        Jedis jedis = getJedis();
        if(jedis != null){
            try{
                jedis.select(db);
                jedis.del(key);
            }catch(Exception e){
                e.printStackTrace();
            } finally{
                returnResource(jedis);
            }
        }
    }

    /**
     * 存放字符串
     * @param db
     * @param key
     * @param value
     * @param expireTime
     */
    public static void setString(int db,String key,String value,int expireTime){
        Jedis jedis = getJedis();
        if(jedis != null){
            jedis.select(db);
            try{
                jedis.set(key, value);
                // redis中session过期时间
                jedis.expire(key, expireTime);
            } catch(Exception e){
                e.printStackTrace();
            } finally{
                returnResource(jedis);
            }
        }
    }

    /**
     * 获取字符串
     * @param db
     * @param key
     * @param expireTime
     * @return
     */
    public static String getString(int db,String key,int expireTime){
        Jedis jedis = getJedis();
        String result = null;
        if(jedis != null){
            jedis.select(db);
            try{
                result = jedis.get(key);
                if(StringUtils.isNotBlank(result)){
                    jedis.expire(key,expireTime);
                }
            }catch(Exception e){
                e.printStackTrace();
            } finally{
                returnResource(jedis);
            }
        }
        return result;
    }

    /**
     * 更新string类型的数据，主要更新过期时间
     * @param key
     */
    public static void updateString(int db,String key,String value,int expireTime){
        Jedis jedis = getJedis();
        if(jedis != null){
            try{
                // redis中session过期时间
                jedis.select(db);
                jedis.set(key, value);
                jedis.expire(key, expireTime);
            }catch(Exception e){
                e.printStackTrace();
            } finally{
                returnResource(jedis);
            }
        }
    }
    /**
     * 更新string类型的数据，主要更新过期时间
     * @param key
     */
    public static void updateString(int db,String key,int expireTime){
        Jedis jedis = getJedis();
        if(jedis != null){
            try{
                // redis中token过期时间
                jedis.select(db);
                jedis.expire(key, expireTime);
            }catch(Exception e){
                e.printStackTrace();
            } finally{
                returnResource(jedis);
            }
        }
    }

}

